/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package GameServer;

import ClientBL.Event;
import Monopol.MonopolExceptions.MonopolErrors;
import ClientBL.GameDetailsResult;
import ClientBL.MonopolyResult;
import Utils.GameDetails;
import Utils.LoadInfo;
import java.util.Collections;
import java.util.List;
import java.util.Timer;
import java.util.TimerTask;


/**
 *
 * @author Assaf
 */
public class ServerService {
    private static ServerService instance;
    private final BackendService backendService;
    private Integer lastEvent;

    static {
        instance = new ServerService();
    }

    public ServerService()
    {
	// Initialize the BackEnd Service
        backendService = new BackendService();
	// Initialize the Last Event Received
	lastEvent = 0;
    }

    public static ServerService getInstance() {
        return instance;
    }

    /**
     * Schedules a Poling timer for polling the Events from the server
     * @param timerName The Time Name
     * @param task The Task to Perform
     * @param delay The Delay Amount
     * @param period The Period of time to Perform
     * @return The Timer Object
     */
    public Timer startPolling (String timerName, TimerTask task, int delay, int period) {
        Timer timer = new Timer (timerName, true);
        timer.scheduleAtFixedRate(task, delay*1000, period*1000);
        return timer;
    }

    /**
     * Returns the Game XSD Schema
     * @return The Response of the Schema as JAXB Element
     */
    public String getGameBoardSchema() {
	return backendService.getGameBoardSchema();
    }

    /**
     * Returns the Game XML File
     * @return The Response for the XML File as JAXB Element
     */
    public String getGameBoardXML() {
	return backendService.getGameBoardXML();
    }

    /**
     * Starts the Required Game
     * @param gameName The Game Name
     * @param humanPlayers The Number of Human Players
     * @param computerizedPlayers The Number of Computer Players
     * @param useAutomaticDiceRoll Using Automatic Dice for Player or Not
     * @return A {@link MonopolyResult} Class
     * @throws MonopolErrors Monopoly Errors as {@link MonopolErrors}
     */
    public void startGame(String gameName, int humanPlayers, int computerizedPlayers, boolean useAutomaticDiceRoll) throws MonopolErrors {
	MonopolyResult startGame = backendService.startGame(gameName, humanPlayers, computerizedPlayers, useAutomaticDiceRoll);
	if (startGame.isError()) {
	    throw new MonopolErrors(startGame.getErrorMessage().getValue());
	}
    }

    /**
     * Returns the Current Game Details
     * @param gameName The Game Name Requested for details
     * @return The Game Details as {@link GameDetailsResult}
     */
    public GameDetails getGameDetails(String gameName) {
	return backendService.getGameDetails(gameName);
    }

    /**
     * Get All the Waiting Games
     * @return An Array of Waiting Game Names
     */
    public String[] getWaitingMonopolyGames() {
        List<String> waitingGames = backendService.getWaitingGames();
        return waitingGames.toArray(new String[0]);
    }

    /**
     * Gets the List of Active Games running on the Server
     * @return A list of Strings holding the Active Games Names
     */
    public String[] getActiveMonopolyGames() {
        List<String> activeGames = backendService.getActiveGames();
        return activeGames.toArray(new String[0]);
    }

    /**
     * Joins The Player to a Monopoly Game
     * @param gameName The Monopoly Game to Join
     * @param playerName The Playing Player Name
     * @return The Monopoly Game ID
     */
    public Integer joinPlayer(String gameName, String playerName) {
        return backendService.joinGame(gameName, playerName);
    }

    /**
     * Gets All the Players Details in the Game
     * @param gameName The Game Name
     * @return An object of Player Details Lists
     * @throws Monopol.MonopolExceptions.MonopolErrors Monopoly Errors as {@link MonopolErrors}
     */
    public List<LoadInfo> getPlayersDetails(String gameName) {
        return backendService.getPlayersDetails(gameName);
    }

    /**
     * Returns All the Events the Monopoly Server Generated
     * @return The New Events that were Added in the Monopoly Server
     */
    public List<Event> getGameEvents() {
	try{
	    List<ClientBL.Event> allEvents = backendService.getAllEvents(lastEvent);
	    if (allEvents != null) {
		lastEvent += allEvents.size();
	    }
	    return allEvents;
	}
	catch(Exception e){
//	    e.printStackTrace();
	    return Collections.emptyList();
	}

        
    }
	
    /**
     * Sets the Dices Result - Using Non-Automatic Dices
     * @param playerID The Player who "threw" the Dices
     * @param dice1 The Result of the First Dice
     * @param dice2 The Result of the Second Dice
     * @return If the Action was Successful
     */
    public Boolean setDiceRollResults(int playerID, Integer eventID, int dice1, int dice2) throws MonopolErrors{
        return backendService.setDiceRollresults(playerID, eventID, dice1, dice2);
    }

    /**
     * Resigns a Player from the Game
     * @param playerID The Player Index that wants to resign
     * @return If the resign was Successful or not
     */
    public Boolean resign(int playerID) throws MonopolErrors {
	return backendService.resign(playerID);
    }

    /**
     * Informs the Server that the Player Bought an Asset
     * @param playerID The Player ID
     * @return If the Buy Action was Successful
     */
    public Boolean buyAsset(int playerID, Integer eventID, Boolean toBuy) throws MonopolErrors{
	    return backendService.buy(playerID, eventID, toBuy);
    }

    /**
     * Informs the Server that the Player Bought a House
     * @param playerID The Player ID
     * @return If the Buy Action was Successful
     */
    public Boolean buyHouse(int playerID, Integer eventID, Boolean toBuy) throws MonopolErrors{
	try{
	return backendService.buy(playerID, eventID, toBuy);
	} catch (MonopolErrors ex) {
	    throw ex;
	}
    }

    /**
     * Sets the Server Name that The Backend Service Connects to
     * @param serverName The Server Name to Connect to
     * @param serverPort The Server Port to Connect With
     */
    public void setServerName(String serverName, Integer serverPort) {
	backendService.setServerName(serverName, serverPort);
    }
}
